# team/views.py

import os
import pandas as pd
from django.shortcuts import get_object_or_404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status, viewsets, permissions
from django.conf import settings
from .models import ExcelFile, Person
from .serializers import ExcelFileUploadSerializer, ExcelFileSerializer, PersonSerializer
from django.db import transaction
from rest_framework.decorators import action  # 确保导入了 action
from django_filters.rest_framework import DjangoFilterBackend


class UploadExcelView(APIView):
    permission_classes = [permissions.AllowAny]  # 根据需求调整权限

    def post(self, request, format=None):
        serializer = ExcelFileUploadSerializer(data=request.data)
        if serializer.is_valid():
            uploaded_file = serializer.validated_data['file']
            date = serializer.validated_data['date']
            device_id = serializer.validated_data['device_id']

            # 确定文件保存目录
            excel_dir = os.path.join(settings.MEDIA_ROOT, 'excel_files')
            os.makedirs(excel_dir, exist_ok=True)

            # 获取文件名并确保其具有正确的扩展名
            file_name = uploaded_file.name
            if not (file_name.endswith('.xlsx') or file_name.endswith('.xls')):
                return Response({'error': '文件格式必须为 .xlsx 或 .xls'}, status=status.HTTP_400_BAD_REQUEST)

            file_path = os.path.join(excel_dir, file_name)

            # 保存文件到文件系统
            with open(file_path, 'wb+') as destination:
                for chunk in uploaded_file.chunks():
                    destination.write(chunk)

            # 创建 ExcelFile 实例
            excel_file = ExcelFile.objects.create(
                file_name=file_name,
                date=date,
                file_directory=excel_dir,
                file_path=file_path,
                device_id=device_id,
                is_deleted=False
            )

            # 解析 Excel 文件并创建 Person 实例
            try:
                # 读取 Excel 文件
                if file_name.endswith('.xlsx'):
                    df = pd.read_excel(file_path, header=1)  # 跳过第一行
                elif file_name.endswith('.xls'):
                    df = pd.read_excel(file_path, header=1, engine='xlrd')  # 跳过第一行

                # 确保所需的列存在
                expected_columns = ['序号', '姓名（昵称）', '电话', '备注']
                if not all(col in df.columns for col in expected_columns):
                    raise ValueError('Excel 文件缺少必要的列。预期列：序号, 姓名, 电话, 备注')

                # 重命名列以匹配模型字段
                df = df.rename(columns={
                    '序号': 'serial_number',
                    '姓名（昵称）': 'name',
                    '电话': 'phone',
                    '备注': 'notes'
                })

                # 删除缺失序号或姓名的行
                df = df.dropna(subset=['serial_number', 'name'])

                # 创建 Person 实例列表
                persons = []
                for _, row in df.iterrows():
                    serial_number = row['serial_number']
                    name = row['name']
                    phone = row['phone'] if pd.notna(row['phone']) else ''
                    notes = row['notes'] if pd.notna(row['notes']) else ''

                    person = Person(
                        serial_number=int(serial_number),
                        excel_file=excel_file,
                        name=str(name),
                        status='0',  # 或根据需求设置
                        phone=str(phone),
                        device_id='',  # 如果有设备ID，可以从其他来源获取
                        notes=str(notes)
                    )
                    persons.append(person)

                # 使用事务确保原子性
                with transaction.atomic():
                    Person.objects.bulk_create(persons)

                return Response({'message': '文件上传并成功保存数据'}, status=status.HTTP_201_CREATED)

            except Exception as e:
                # 如果解析失败，删除已保存的文件和 ExcelFile 实例
                excel_file.delete()
                os.remove(file_path)
                return Response({'error': f'解析文件失败: {str(e)}'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class ExcelFileViewSet(viewsets.ModelViewSet):
    """
    ExcelFile 的 ViewSet，包括列表、检索、创建、更新和逻辑删除。
    """
    serializer_class = ExcelFileSerializer
    queryset = ExcelFile.objects.filter(is_deleted=False)  # 仅查询未删除的记录
    permission_classes = [permissions.AllowAny]  # 根据需求调整权限
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['file_name', 'date', 'is_deleted']

    def get_queryset(self):
        """
        重写 get_queryset 以支持过滤未删除的记录。
        """
        return ExcelFile.objects.filter(is_deleted=False)

    def destroy(self, request, *args, **kwargs):
        """
        重写 destroy 方法，实现逻辑删除。
        """
        instance = self.get_object()
        instance.is_deleted = True
        instance.save()
        return Response(status=status.HTTP_204_NO_CONTENT)

    @action(detail=True, methods=['get'], url_path='persons')
    def list_persons(self, request, pk=None):
        """
        获取关联的人员信息，通过 ExcelFile 的 ID。
        """
        excel_file = self.get_object()
        persons = excel_file.persons.all()
        serializer = PersonSerializer(persons, many=True)
        return Response(serializer.data)


class PersonViewSet(viewsets.ReadOnlyModelViewSet):
    """
    Person 的 ViewSet，仅提供读取接口。
    """
    serializer_class = PersonSerializer
    queryset = Person.objects.all()
    permission_classes = [permissions.AllowAny]  # 根据需求调整权限
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['name', 'phone', 'device_id', 'status', 'excel_file__id']

    def get_queryset(self):
        """
        根据 URL 参数中的 excel_file_id 过滤人员信息。
        """
        excel_file_id = self.request.query_params.get('excel_file_id', None)
        if excel_file_id is not None:
            return Person.objects.filter(excel_file__id=excel_file_id)
        return Person.objects.all()


class UpdatePersonView(APIView):
    """
    使用 PUT/PATCH 更新指定 Person 记录
    """

    def put(self, request, pk, format=None):
        """
        全量更新人员信息
        """
        person = get_object_or_404(Person, pk=pk)
        serializer = PersonSerializer(person, data=request.data)

        if serializer.is_valid():
            serializer.save()
            return Response({'message': '人员信息已全量更新'}, status=status.HTTP_200_OK)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def patch(self, request, pk, format=None):
        """
        局部更新人员信息
        """
        person = get_object_or_404(Person, pk=pk)
        serializer = PersonSerializer(person, data=request.data, partial=True)

        if serializer.is_valid():
            serializer.save()
            return Response({'message': '人员信息已局部更新'}, status=status.HTTP_200_OK)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
